package com.atzly.community.datasource;

import com.google.common.collect.Maps;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.DeleteBuilder;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.apache.zookeeper.CreateMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

/**
 * @author zlysimida
 * @date 2022/11/27 - 13:07
 */
@Component
public class ZookeeperService {

    @Autowired
    private CuratorFramework curatorFramework;

    public String createPath(String path, String context, CreateMode mode) {
        try {
            String result = curatorFramework.create()
                    .creatingParentsIfNeeded()
                    .withMode(mode)
                    .forPath(path, context.getBytes(StandardCharsets.UTF_8));
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public String createEphemeralPath(String path, String context) {
        return createPath(path, context, CreateMode.EPHEMERAL);
    }

    public String createPersistentPath(String path, String context) {
        return createPath(path, context, CreateMode.PERSISTENT);
    }

    public String createSequentialPath(String path, String context, Integer mode) {
        CreateMode createMode = null;
        if (mode == 1) {
            createMode = CreateMode.PERSISTENT_SEQUENTIAL;
        }else if (mode == 2) {
            createMode = CreateMode.EPHEMERAL_SEQUENTIAL;
        }
        return createPath(path,context,createMode);
    }

    /**
     * 删除节点
     * @param path 节点
     * @param recursive 是否递归删除
     */
    public void delete(String path, boolean recursive) {
        DeleteBuilder delete = curatorFramework.delete();
        try {
            if (recursive) {
                delete.deletingChildrenIfNeeded()
                        .forPath(path);
            }else {
                delete.forPath(path);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String get(String path) {
        byte[] bytes = null;
        try {
            bytes = curatorFramework.getData().forPath(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bytes == null ? null : new String(bytes, StandardCharsets.UTF_8);
    }

    public void update(String path, String context) {
        try {
            curatorFramework.setData()
                    .forPath(path,context.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Map<String, String> getList(String path, String prefix ) {
        Map<String, String> result = Maps.newHashMap();
        try {
            List<String> dirs = curatorFramework.getChildren().forPath(path);

            dirs.stream().forEach(item -> {
                String value = get(path + "/" + item);

                if (!StringUtils.isEmpty(prefix)) {
                    item = prefix + "." + item;
                }
                result.put(item, value);
            });

            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public void addListener(String path, TreeCacheListener treeCacheListener) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    TreeCache treeCache = TreeCache.newBuilder(curatorFramework, path).setCacheData(true).build();
                    treeCache.getListenable().addListener(treeCacheListener);
                    treeCache.start();
                    ZookeeperListenerHolder.ZK_LISTENER_CACHES.put("listenerChange",treeCache);
                    Thread.sleep(Integer.MAX_VALUE);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        thread.setDaemon(false);
        thread.start();
    }

    public void shutDownClient() {
        curatorFramework.close();
    }

    public static void main(String[] args) {
        String s = new String(null,StandardCharsets.UTF_8);
        System.out.println(s);
    }

}
